package com.yuwen.yuwenRPC.utils;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.setting.dialect.Props;
import org.yaml.snakeyaml.Yaml;

import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * @ClassNameConfigUtils
 * @Description TODO
 * @Author钰玟
 * @Date2025/3/30 下午12:55
 * @Version 1.0
 **/


/**
 * 配置工具类
 */
public class ConfigUtils {


    /**
     * 加载配置对象
     * @param clazz 所需加载配置项的类
     * @param prefix 配置前缀
     * @return 配置项
     * @param <T> 泛型
     */
    public static <T> T loadConfig(Class<T> clazz,String prefix ) {
        return loadConfig(clazz,prefix,"");
    }

    /**
     *
     * 加载配置对象
     * @param clazz 所需加载配置项的类
     * @param prefix 配置前缀
     * @param environment 生产环境  - test / dev / pro
     * @return 配置项x
     * @param <T> 泛型
     */
    public static <T> T loadConfig(Class<T> clazz,String prefix,String environment) {
        /**
         * 适配 yaml文件
         */
        // 根据环境变量拼接字符串生成环境变量配置
        StringBuilder configFileBuilder = new StringBuilder("application");
        if (StrUtil.isNotBlank(environment)) {
            configFileBuilder.append("-").append(environment);
        }
        configFileBuilder.append(".yml"); // 支持 YML 文件

        // 尝试加载 YAML 文件
        T config = loadYamlConfig(clazz, configFileBuilder.toString(), prefix);

        //加载yaml文件失败
        if (config == null) {
            //清空 StringBuilder
            configFileBuilder.setLength(0);
            // 由环境变量 拼接字符串 生成 环境变量配置
            configFileBuilder = new StringBuilder("application");
            if(StrUtil.isNotBlank(environment)) {
                //environment 不为空
                configFileBuilder.append("-").append(environment);
            }
            configFileBuilder.append(".properties");
//        生成配置文件
            Props props = new Props(configFileBuilder.toString());

            /**
             * 开启自动变更
             */
            props.autoLoad(true);
            //将配置项装配到 配置类
            return props.toBean(clazz,prefix);
        }
        return config;
    }

    /**
     * 加载yaml文件
     * @param clazz 配置类
     * @param configFileName 配置文件名称
     * @param prefix 配置前缀
     * @return Map
     * @param <T> 泛型
     */
    public static <T> T loadYamlConfig(Class<T> clazz,String configFileName,String prefix) {
        Yaml yaml = new Yaml();
        try {
            //从类路径获取 yml文件 并转化为 输入流
            InputStream inputStream = clazz.getClassLoader().getResourceAsStream(configFileName);
            if (inputStream == null) {
                //为null
                return null;
            }
            //转化为 键值对
            Map<String,Object> data =  yaml.load(inputStream);
            return  populateConfig(clazz, data, prefix);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 装配配置项至配置类
     * @param clazz 配置类
     * @param data 配置Map
     * @param prefix 前缀
     * @return 配置项
     * @param <T> 泛型
     */
    private static <T> T populateConfig(Class<T> clazz, Map<String, Object> data, String prefix) {
        // 创建一个用于存放符合条件的新 map
        Map<String, Object> filteredData = new HashMap<>();
        // 遍历原始数据，筛选以 prefix 作为前缀的字段
        for (Map.Entry<String, Object> entry : data.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            // 检查key是否以prefix开头
            if (key.startsWith(prefix)) {
                // 去掉前缀，构建新的键名
                String newKey = key.substring(prefix.length());
                // 去掉可能的前导点或者空白（如果有的话）
                if (newKey.startsWith(".")) {
                    newKey = newKey.substring(1);
                }
                if (newKey.startsWith(" ")) {
                    newKey = newKey.substring(1);
                }
                filteredData.put(newKey, value);
            }
        }
        Collection<Object> values = filteredData.values();
        Map<String, Object> resultMap = values.stream()
                .filter(map -> map instanceof Map) // 确保每个对象都是 Map 的实例
                .flatMap(map -> ((Map<?, ?>) map).entrySet().stream()) // 将每个 Map 转为 Stream<Map.Entry>
                .collect(Collectors.toMap(
                        entry -> (String) entry.getKey(), // 键
                        entry -> entry.getValue(), // 值
                        (existing, replacement) -> replacement // 处理键冲突
                ));
        // 用过滤后的数据填充目标对象
        return BeanUtil.mapToBean(resultMap, clazz, true);
    }

}
